#pragma once
#include "stdafx.h"
#include <boost/noncopyable.hpp>
#include <event2/event.h>
#include <event2/buffer.h>
#include <event2/bufferevent.h>
#include <boost/shared_ptr.hpp>
#include <boost/unordered_map.hpp>  
#include "SocketStreamInput.h"
#include "SocketStreamOutput.h"
#include "CommandManager.h"

/*
 * IOManager is used to deal with socket
 */
class IOManager:private boost::noncopyable
{
private:
	static IOManager * ioManager;
	boost::unordered_map<SocketStreamOutput*, struct evbuffer*> outputMap;//map each SocketStreamOutput to one output buffer
	struct event_base * base;

	static void errorcb(struct bufferevent *bev, short error, void *ctx);
	//stream input
	static void input_accept(evutil_socket_t listener, short event, void *arg);
	static void input_read(struct bufferevent *bev, void *ctx);
	//stream output
	static void output_connected(struct bufferevent *bev, short events, void *ptr);

	//command input
	static void command_read(struct bufferevent *bev, void *ctx);
	static void command_accept(evutil_socket_t listener, short event, void *arg);
	//the thread function. loop and check if some event is ready, if yes,  the registered function handler would be called
	void createNewThreadToPerfromIO(void);
public:
	
	 
	
	IOManager(void);
	~IOManager(void);
	static IOManager* getInstance(void);
	//receive the input stream by socket 
	void addStreamInput(std::string ip,std::string port, SocketStreamInput* streamInput);

	//export the output stream by socket 
	bool addStreamOutput(std::string ip,std::string port, SocketStreamOutput* streamOutput);
	
	//write output to the socket
	bool writeOutput(char* buffer, int length,SocketStreamOutput* streamOutput);

	//receive command by socket
	void addCommandInput(std::string ip,std::string port, CommandManager* commandManager);

	//create a new thread to deal with the IO
	void execute(void);
	 
};

